package org.shangrila.bme.mb;

import java.io.Serializable;
import java.math.BigDecimal;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.enterprise.context.SessionScoped;
import javax.faces.model.SelectItem;
import javax.inject.Named;

import org.primefaces.event.RowEditEvent;
import org.shangrila.app.sys.cfg.AppInitInfo;
import org.shangrila.app.sys.shiro.SecUtil;
import org.shangrila.bme.eo.AppFileInfo;
import org.shangrila.bme.eo.BmeContProd;
import org.shangrila.bme.eo.BmeContPurch;
import org.shangrila.bme.eo.BmeContract;
import org.shangrila.bme.eo.BmeCustomer;
import org.shangrila.bme.eo.BmeInvInfo;
import org.shangrila.bme.eo.BmePayroll;
import org.shangrila.comm.dao.DbAccess;
import org.shangrila.comm.helper.IDHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

/**  
* <p>Title: InvInfoMB</p>  
* <p>Description: </p>  
* @author 赵功就  
* @date 2018年8月17日  
*/
@Named
@SessionScoped
public class InvInfoMB implements Serializable{

	/** serialVersionUID*/
	private static final long serialVersionUID = -6923090424706611814L;
	
	private final Logger log = LoggerFactory.getLogger(this.getClass());
	
	private String operator="test";
	
	//获取相关数据字典
	private List<SelectItem> itemsInvInfoStatus = AppInitInfo.getDropdownList("InvInfoStatus");
	
	@Autowired
	private DbAccess db;
	
	private BmeInvInfo io=new BmeInvInfo();
	
	private BmeContract selectedContract=new BmeContract();
	
	
	private List<BmeContract> bmeContracts;
	
	/** vod：所选合同带出的请款单集合*/
	private List<BmePayroll> vod=new ArrayList<BmePayroll>();
	private BmeInvInfo selected=new BmeInvInfo();
	private List<BmePayroll> selectedVod=new ArrayList<>();
	
	/** selectedRtn：回款单详情*/
	private List<BmeInvInfo> selectedRtn=new ArrayList<>();
	
	/** payAmounts :请款总额*/
	private BigDecimal payAmounts=new BigDecimal(0);
	
	
	
	public List<BmeInvInfo> getSelectedRtn() {
		return selectedRtn;
	}

	public void setSelectedRtn(List<BmeInvInfo> selectedRtn) {
		this.selectedRtn = selectedRtn;
	}

	public List<BmePayroll> getSelectedVod() {
		return selectedVod;
	}

	public void setSelectedVod(List<BmePayroll> selectedVod) {
		this.selectedVod = selectedVod;
	}

	public BigDecimal getPayAmounts() {
		return payAmounts;
	}

	public void setPayAmounts(BigDecimal payAmounts) {
		this.payAmounts = payAmounts;
	}

	public List<SelectItem> getItemsInvInfoStatus() {
		return itemsInvInfoStatus;
	}

	public void setItemsInvInfoStatus(List<SelectItem> itemsInvInfoStatus) {
		this.itemsInvInfoStatus = itemsInvInfoStatus;
	}

	public List<BmePayroll> getVod() {
		return vod;
	}

	public void setVod(List<BmePayroll> vod) {
		this.vod = vod;
	}

	public BmeInvInfo getSelected() {
		return selected;
	}

	public void setSelected(BmeInvInfo selected) {
		this.selected = selected;
	}

	public List<BmeContract> getBmeContracts() {
		return bmeContracts;
	}

	public void setBmeContracts(List<BmeContract> bmeContracts) {
		this.bmeContracts = bmeContracts;
	}

	public BmeContract getSelectedContract() {
		return selectedContract;
	}

	public void setSelectedContract(BmeContract selectContract) {
		this.selectedContract = selectContract;
	}

	public BmeInvInfo getIo() {
		return io;
	}

	public void setIo(BmeInvInfo io) {
		this.io = io;
	}

	@PostConstruct
	public void init() {
		
		log.info("@PostConstruct..."+this.getClass());
		newIo();
		
		BmeCommEntityService service = AppInitInfo.findMBeanByName("bmeCommEntityService",BmeCommEntityService.class);
    	bmeContracts = service.getBmeContracts();
    	//selectedContract = bmeContracts.get(0);

		if(null!=selectedContract) {
			vod=selectedContract.getBmePayrolls();
		}
		try{
			operator = SecUtil.getCachedShiroUser().getUserno();
		}
		catch(Exception ex){
			operator="bme";
		}
	}
	
	public void newIo(BmeInvInfo bmeInvInfo) {
		bmeInvInfo.setId(IDHelper.genStrIDs(24));
		bmeInvInfo.setInvId(io.getInvId());
		bmeInvInfo.setAmount(io.getAmount());
		bmeInvInfo.setInvDate(io.getInvDate());
		bmeInvInfo.setStatus(io.getStatus());
		bmeInvInfo.setBmeContract(selectedContract);
		bmeInvInfo.setContName(selectedContract.getName());
		bmeInvInfo.setCustName(selectedContract.getCustName());
		bmeInvInfo.setCreateTime(new Date());
		bmeInvInfo.setOperator(operator);
		bmeInvInfo.setStatus("1");
	}
	
	@PreDestroy
	public void after() {
		
	}
	
	/**  
	 * <p>Title: savePayroll</p>  
	 * <p>Description: 选择请款单</p>  
	 * @return  
	 */
	public String selectPayroll() {

		for (int j = 0; j < selectedVod.size(); j++) {
			BmeInvInfo bmeInvInfo = new BmeInvInfo();

			if (selectedRtn.size() == 0) {
				newIo(bmeInvInfo);
				bmeInvInfo.setBmePayroll(selectedVod.get(j));
				bmeInvInfo.setPayAmount(selectedVod.get(j).getAmount());
				selectedRtn.add(bmeInvInfo);
			} else {

				for (int i = 0; i < selectedRtn.size(); i++) {
					if (selectedVod.contains(selectedRtn.get(i).getBmePayroll())) {
						selectedVod.remove(selectedRtn.get(i).getBmePayroll());
					}
				}

				if (selectedVod.size() > 0) {
					for (BmePayroll bmePayroll : selectedVod) {
						newIo(bmeInvInfo);
						bmeInvInfo.setBmePayroll(bmePayroll);
						bmeInvInfo.setPayAmount(bmePayroll.getAmount());
						selectedRtn.add(bmeInvInfo);
					}
				}
			}

		}
		
		//判断已选中的汇款单，通过合同编号、请款单号，在数据库中是否有对应的回款记录
				StringBuilder sql=new StringBuilder("SELECT rt FROM BmeInvInfo rt ");
				StringBuilder where=new StringBuilder("WHERE rt.bmeContract=?1 AND rt.bmePayroll=?2");
				sql.append(where.toString());
				List<Object> params=new ArrayList<>();
				for (BmeInvInfo bmeInvInfo : selectedRtn) {
					params.add(0, bmeInvInfo.getBmeContract());
					params.add(1, bmeInvInfo.getBmePayroll());
					List<BmeInvInfo> bmeInvInfos = db.findBySql(sql.toString(),params.toArray());
					
					//根据该请款单是否有请款记录进行相应处理
					if(bmeInvInfos.isEmpty()) {
						bmeInvInfo.setInvAmount(new BigDecimal("0"));
						bmeInvInfo.setInvPercent("0.00%");
					}else {
						
						List<BigDecimal> maxs=new ArrayList<BigDecimal>();
						BigDecimal sum=new BigDecimal("0");//已回款
						for (BmeInvInfo inv : bmeInvInfos) {
							maxs.add(inv.getInvAmount());
						}
						sum=Collections.max(maxs);
						BigDecimal divide = sum.divide(bmeInvInfo.getPayAmount(),2,BigDecimal.ROUND_HALF_UP);
						NumberFormat instance = NumberFormat.getPercentInstance();
						instance.setMaximumFractionDigits(2);
						bmeInvInfo.setInvAmount(sum);
						bmeInvInfo.setInvPercent(instance.format(divide.doubleValue()));
					}
				}
		
		return null;
	}
	
	/**  
	 * <p>Title: delPayroll</p>  
	 * <p>Description: 删除已经选择的请款单</p>  
	 * @return  
	 */
	public String delPayroll() {
		
		selectedRtn.remove(selected);
		AppInitInfo.showMessage("记录移除", "处理成功");
		return null;
	}

	/**  
	 * <p>Title: onRowEdit</p>  
	 * <p>Description: 对开票单详情进行行编辑</p>  
	 * @param event  
	 */
	public void onRowEdit(RowEditEvent event) {
		
		selected=selectedRtn.get(selectedRtn.indexOf((BmeInvInfo)event.getObject()));//获取行编
		List<BigDecimal> maxs=new ArrayList<BigDecimal>();
		BigDecimal sum = new BigDecimal("0");//回款金额累计
		
		//1、查询该请款单在数据库中的请款集合，获取请款总额
		StringBuilder sql=new StringBuilder("SELECT rt FROM BmeInvInfo rt ");
		StringBuilder where=new StringBuilder("WHERE rt.bmeContract=?1 AND rt.bmePayroll=?2");
		sql.append(where.toString());
		List<Object> params=new ArrayList<>();
		
		params.add(0, selected.getBmeContract());
		params.add(1, selected.getBmePayroll());
		for (@SuppressWarnings("unused") BmeInvInfo bmeInvInfo : selectedRtn) {
			List<BmeInvInfo> bmeInvInfos = db.findBySql(sql.toString(),params.toArray());
			if(!bmeInvInfos.isEmpty()) {
				for (BmeInvInfo inv : bmeInvInfos) {
					maxs.add(inv.getInvAmount());
				}
			}else {
				maxs.add(new BigDecimal("0"));
			}
		}
		
		//2、判断开票金额是否大于请款金额
		BigDecimal invAmount = selected.getInvAmount();
		BigDecimal payAmount = selected.getPayAmount();
		if(invAmount.compareTo(payAmount)==1) {
			AppInitInfo.showMessage("输入金额错误", "已开票金额不能大于请款金额");
		}else {
			//计算回款金额
			BigDecimal max = Collections.max(maxs);
			if(payAmount.compareTo(max)==0||payAmount.compareTo(max)==-1) {
				AppInitInfo.showMessage("消息提醒", "该请款单开票已经完成");
				return;
			}else {
				if (max.compareTo(invAmount)==1||max.compareTo(invAmount)==0) {
					AppInitInfo.showMessage("已开票有误", "已开票数为："+max);
					return;
				}else {
					
					sum=sum.add(invAmount.subtract(Collections.max(maxs)));
					io.setAmount(sum);
				}
			}
			
			//重置回款比例
			BigDecimal divide = invAmount.divide(payAmount,2,BigDecimal.ROUND_HALF_UP);
			NumberFormat percent = NumberFormat.getPercentInstance();
			percent.setMaximumFractionDigits(2);
			
			selected.setInvPercent(percent.format(divide));
		}
		
		AppInitInfo.showMessage("请款信息", "修改成功");
		
	}
	
	/**  
	 * <p>Title: onRowCancel</p>  
	 * <p>Description: 取消编辑开票单详情</p>  
	 * @param event  
	 */
	public void onRowCancel(RowEditEvent event) {
		
		AppInitInfo.showMessage("取消修改", "处理成功");
	}
	
	
	/**  
	 * <p>Title: saveAction</p>  
	 * <p>Description: 保存开票单</p>  
	 * @return  
	 */
	public String saveAction() {
		
		
		if(selectedRtn.size()==0) {
			AppInitInfo.showMessage("开票单为空", "存在开票单详情才能保存");
		}else {
			
			db.beginTransaction();
			for (BmeInvInfo invInfo : selectedRtn) {
				invInfo.setAmount(io.getAmount());
				invInfo.setStatus("2");
				db.insert(invInfo);
			}
			db.commitTransaction();
			AppInitInfo.showMessage("保存开票", "保存开票成功");
			
		}
		
		
		return null;
	}
	
	public void newIo() {
    	io = new BmeInvInfo();
    	io.setId(IDHelper.genStrID(24));
    	io.setInvId(IDHelper.genStrIDs(24));
    	io.setStatus("1");
    	selectedContract=null;
    	vod=null;
    	selected=null;
    }
	
	public String commitAction() {
		newIo();
		
		return null;
	}
	
	//选择合同
	public void onSelectedContract() {
		
		selectedRtn.clear();	
		if(null!=selectedContract) {
			vod=selectedContract.getBmePayrolls();
		}
		
	}
}
